package com.yao.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yao.system.entity.*;
import com.yao.system.entity.dto.JobSerachDTO;
import com.yao.system.entity.dto.UserDTO;
import com.yao.system.entity.vo.JobVO;
import com.yao.system.mapper.JobMapper;
import com.yao.system.service.*;
import com.yao.system.util.UserContext;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;

@Slf4j
@Service
@RequiredArgsConstructor
public class JobServiceImpl extends ServiceImpl<JobMapper, Job> implements IJobService {

    private final ICompanyService companyService;
    private final IUserJobService userJobService;
    private final IUserService userService;
    private final IJobCollectionService collectionService;
    private final IJobResumeService jobResumeService;
    private final ThreadPoolExecutor jobThreadPool;

    @Override
    public Result addJob(Job job) {
        if (!isTrueOfParameter(job)) {
            return Result.error("必填信息不能为空");
        }
        UserDTO user = UserContext.getUser();
        Company company = companyService.lambdaQuery()
                .eq(Company::getUserId, user.getId())
                .one();
        job.setUserId(user.getId());
        job.setUserName(user.getName());
        job.setImage(user.getImage());
        job.setCompanyId(company.getId());
        job.setCompany(company.getName());
        job.setAddress(company.getAddress());
        save(job);
        UserJob userJob = new UserJob();
        userJob.setUserId(user.getId());
        userJob.setJobId(job.getId());
        userJobService.save(userJob);
        return Result.ok("发布成功");
    }

    /**
     * 分页查询岗位列表
     */
    @Override
    public Result getList(Integer page, Integer size, JobSerachDTO dto) {
        UserDTO user = UserContext.getUser();

        if (page == null) page = 1;
        if (size == null) size = 9;
        Page<Job> page1 = null;
        if (dto != null) {
            page1 = lambdaQuery()
                    .eq(StrUtil.isNotEmpty(dto.getCity()), Job::getAddress, dto.getCity())
                    .like(StrUtil.isNotBlank(dto.getContent()), Job::getTitle, dto.getContent())
                    //.or()
                    //.like(StrUtil.isNotBlank(dto.getContent()), Job::getCompany, dto.getContent())
                    //.like(StrUtil.isNotBlank(dto.getContent()), Job::getContent, dto.getContent())
                    .eq(StrUtil.isNotBlank(dto.getEducational()), Job::getEducational, dto.getEducational())
                    .eq(StrUtil.isNotBlank(dto.getJobCatogray()), Job::getJobType, dto.getJobCatogray())
                    .eq(StrUtil.isNotBlank(dto.getJobExperience()), Job::getExperience, dto.getJobExperience())
                    .eq(Job::getType, 1)
                    .orderByDesc(Job::getUpdateTime)
                    .page(Page.of(page, size));
        } else {
            page1 = lambdaQuery()
                    .eq(Job::getType, 1)
                    .orderByDesc(Job::getUpdateTime)
                    .page(Page.of(page, size));
        }

        List<Job> jobList = page1.getRecords();
        int total = (int) page1.getTotal();
        int pages = (int) page1.getPages();

        if (jobList.isEmpty()) {
            return Result.ok(PageResult.of(total, pages, null));
        }

        Set<Long> userIds = new HashSet<>();
        Set<Long> companyIds = new HashSet<>();
        for (Job job : jobList) {
            userIds.add(job.getUserId());
            companyIds.add(job.getCompanyId());
        }

        CompletableFuture<Map<Long, User>> userFuture = CompletableFuture.supplyAsync(() -> {
            return userService.getByIds(userIds);
        }, jobThreadPool);

        CompletableFuture<Map<Long, Company>> companyFuture = CompletableFuture.supplyAsync(() -> {
            return companyService.getByIds(companyIds);
        }, jobThreadPool);

        List<JobCollection> collectionList = collectionService.lambdaQuery()
                .eq(JobCollection::getUserId, user.getId())
                .list();
        Set<Long> collectJob = collectionList.stream()
                .map(collection -> collection.getJobId())
                .collect(Collectors.toSet());

        Map<Long, User> userMap = userFuture.join();
        Map<Long, Company> companyMap = companyFuture.join();

        List<JobVO> voList = new ArrayList<>();
        for (Job job : jobList) {
            JobVO vo = new JobVO();
            BeanUtil.copyProperties(job, vo);
            User user1 = userMap.get(job.getUserId());
            Company company = companyMap.get(job.getCompanyId());
            if (user1 != null) {
                vo.setUserName(user1.getName());
                vo.setImage(user1.getImage());
            }
            if (company != null) {
                vo.setCompany(company.getName());
                //vo.setAddress(company.getAddress());
                vo.setCompanyImage(company.getImage());
            }
            if (collectJob.contains(job.getId())) {
                vo.setIsCollection(1);
            }
            voList.add(vo);
        }

        return Result.ok(PageResult.of(total, pages, voList));
    }

    /**
     * 获取我的岗位收藏列表
     *
     * @param page
     * @param size
     * @return
     */
    @Override
    public Result getMyCollection(Integer page, Integer size) {
        UserDTO user = UserContext.getUser();
        Page<JobCollection> page1 = collectionService.lambdaQuery()
                .eq(JobCollection::getUserId, user.getId())
                .page(Page.of(page, size));
        List<JobCollection> list = page1.getRecords();
        int total = (int) page1.getTotal();
        int pages = (int) page1.getPages();
        if (list == null || list.size() == 0) {
            return Result.ok(PageResult.of(total, pages, null));
        }
        Set<Long> jobIds = new HashSet<>();
        for (JobCollection job : list) {
            jobIds.add(job.getJobId());
        }
        Map<Long, Job> jobMap = getByIds(jobIds);
        Set<Long> userIds = new HashSet<>();
        Set<Long> companyIds = new HashSet<>();
        Collection<Job> values = jobMap.values();
        for (Job job : values) {
            userIds.add(job.getUserId());
            companyIds.add(job.getCompanyId());
        }

        CompletableFuture<Map<Long, User>> userFuture = CompletableFuture.supplyAsync(() -> {
            return userService.getByIds(userIds);
        }, jobThreadPool);

        CompletableFuture<Map<Long, Company>> companyFuture = CompletableFuture.supplyAsync(() -> {
            return companyService.getByIds(companyIds);
        }, jobThreadPool);

        Map<Long, User> userMap = userFuture.join();
        Map<Long, Company> companyMap = companyFuture.join();

        //Set<Long> jobIds = list.stream()
        //        .map(jobCollection -> jobCollection.getJobId())
        //        .collect(Collectors.toSet());
        Collection<Job> jobs = jobMap.values();
        List<JobVO> voList = new ArrayList<>();
        for (Job job : jobs) {
            JobVO vo = new JobVO();
            BeanUtil.copyProperties(job, vo);
            User user1 = userMap.get(job.getUserId());
            if (user1 != null) {
                vo.setImage(user1.getImage());
                vo.setUserName(user1.getName());
            }
            Company company = companyMap.get(job.getCompanyId());
            if (company != null) {
                vo.setCompany(company.getName());
                vo.setCompanyImage(company.getImage());
            }
            voList.add(vo);
        }

        return Result.ok(PageResult.of(total, pages, voList));
    }

    /**
     * 获取用户已投递简历的岗位列表
     *
     * @return
     */
    @Override
    public Result getResumeJobList(Integer page, Integer size) {
        UserDTO user = UserContext.getUser();
        Page<JobResume> page1 = jobResumeService.lambdaQuery()
                .eq(JobResume::getResumeUserId, user.getId())
                .orderByDesc(JobResume::getCreateTime)
                .page(Page.of(page, size));

        List<JobResume> list = page1.getRecords();
        int total = (int) page1.getTotal();
        int pages = (int) page1.getPages();
        if (list == null || list.size() == 0) {
            return Result.ok(PageResult.of(total, pages, null));
        }

        Map<Long, LocalDateTime> createTime = new HashMap<>();
        Set<Long> jobIds = new HashSet<>();
        Set<Long> userIds = new HashSet<>();
        for (JobResume jobResume : list) {
            jobIds.add(jobResume.getJobId());
            userIds.add(jobResume.getJobUserId());
            createTime.put(jobResume.getJobId(), jobResume.getCreateTime());
        }
        Map<Long, Job> jobMap = getByIds(jobIds);
        Set<Long> companyIds = new HashSet<>();
        Collection<Job> values = jobMap.values();
        for (Job job : values) {
            companyIds.add(job.getCompanyId());
        }

        CompletableFuture<Map<Long, User>> userFuture = CompletableFuture.supplyAsync(() -> {
            return userService.getByIds(userIds);
        }, jobThreadPool);

        CompletableFuture<Map<Long, Company>> companyFuture = CompletableFuture.supplyAsync(() -> {
            return companyService.getByIds(companyIds);
        }, jobThreadPool);

        Map<Long, User> userMap = userFuture.join();
        Map<Long, Company> companyMap = companyFuture.join();

        Collection<Job> jobs = jobMap.values();
        List<JobVO> voList = new ArrayList<>();
        for (Job job : jobs) {
            JobVO vo = new JobVO();
            BeanUtil.copyProperties(job, vo);
            User user1 = userMap.get(job.getUserId());
            if (user1 != null) {
                vo.setImage(user1.getImage());
                vo.setUserName(user1.getName());
            }
            Company company = companyMap.get(job.getCompanyId());
            if (company != null) {
                vo.setCompany(company.getName());
                vo.setCompanyImage(company.getImage());
            }
            LocalDateTime time = createTime.get(job.getId());
            vo.setCreateTime(time);
            voList.add(vo);
        }
        Collections.sort(voList, (v1, v2) -> {
            return v2.getCreateTime().compareTo(v1.getCreateTime());
        });

        return Result.ok(PageResult.of(total, pages, voList));
    }

    /**
     * 获取用户已投递简历的岗位列表
     *
     * @return
     */
    /*@Override
    public Result getResumeJobList(Integer page, Integer size) {
        // 参数校验
        if (page == null || size == null || page < 1 || size < 1) {
            return Result.error("Invalid page or size");
        }

        UserDTO user;
        try {
            user = UserContext.getUser();
        } catch (Exception e) {
            // 处理获取用户信息异常
            return Result.error("Failed to get user information");
        }

        Page<JobResume> page1;
        try {
            page1 = jobResumeService.lambdaQuery()
                    .eq(JobResume::getResumeUserId, user.getId())
                    .orderByDesc(JobResume::getCreateTime)
                    .page(Page.of(page, size));
        } catch (Exception e) {
            // 处理查询简历信息异常
            return Result.error("Failed to query resume information");
        }

        if (page1.getRecords() == null || page1.getRecords().isEmpty()) {
            return Result.ok(PageResult.of((int)page1.getTotal(), (int)page1.getPages(), null));
        }

        Map<Long, LocalDateTime> createTime = new HashMap<>();
        Set<Long> jobIds = new HashSet<>();
        Set<Long> userIds = new HashSet<>();
        for (JobResume jobResume : page1.getRecords()) {
            jobIds.add(jobResume.getJobId());
            userIds.add(jobResume.getJobUserId());
            createTime.put(jobResume.getJobId(), jobResume.getCreateTime());
        }

        CompletableFuture<Map<Long, Job>> jobFuture = CompletableFuture.supplyAsync(() -> {
            try {
                return this.getByIds(jobIds);
            } catch (Exception e) {
                // 异常处理，保证线程安全和数据一致性
                return new HashMap<>();
            }
        }, jobThreadPool);

        CompletableFuture<Map<Long, User>> userFuture = CompletableFuture.supplyAsync(() -> {
            try {
                return userService.getByIds(userIds);
            } catch (Exception e) {
                // 异常处理，保证线程安全和数据一致性
                return new HashMap<>();
            }
        }, jobThreadPool);

        CompletableFuture<Map<Long, Company>> companyFuture = CompletableFuture.supplyAsync(() -> {
            Set<Long> companyIds = new HashSet<>();
            Collection<Job> values = jobFuture.join().values();
            for (Job job : values) {
                companyIds.add(job.getCompanyId());
            }
            try {
                return companyService.getByIds(companyIds);
            } catch (Exception e) {
                // 异常处理，保证线程安全和数据一致性
                return new HashMap<>();
            }
        }, jobThreadPool);

        try {
            Map<Long, Job> jobMap = jobFuture.join();
            Map<Long, User> userMap = userFuture.join();
            Map<Long, Company> companyMap = companyFuture.join();

            Collection<Job> jobs = jobMap.values();
            List<JobVO> voList = new ArrayList<>();
            for (Job job : jobs) {
                JobVO vo = new JobVO();
                BeanUtil.copyProperties(job, vo);
                User user1 = userMap.get(job.getUserId());
                if (user1 != null) {
                    vo.setImage(user1.getImage());
                    vo.setUserName(user1.getName());
                }
                Company company = companyMap.get(job.getCompanyId());
                if (company != null) {
                    vo.setCompany(company.getName());
                    vo.setCompanyImage(company.getImage());
                }
                LocalDateTime time = createTime.get(job.getId());
                vo.setCreateTime(time);
                voList.add(vo);
            }
            Collections.sort(voList, (v1, v2) -> v2.getCreateTime().compareTo(v1.getCreateTime()));

            return Result.ok(PageResult.of((int)page1.getTotal(), (int)page1.getPages(), voList));
        } catch (Exception e) {
            // 处理异步操作等待过程中的异常
            return Result.error("Async operation failed");
        }
    }*/


    @Override
    public Result deleteJob(Long id) {
        boolean remove = removeById(id);
        return Result.ok("删除成功");
    }

    @Override
    public Result getJobAndResumeCount() {
        Long count = lambdaQuery()
                .eq(Job::getUserId, UserContext.getUser().getId())
                .count();
        Long count1 = jobResumeService.lambdaQuery()
                .eq(JobResume::getJobUserId, UserContext.getUser().getId())
                .count();
        Map<String, Long> map = new HashMap<>();
        map.put("jobCount", count);
        map.put("resumeCount", count1);
        return Result.ok(map);
    }


    @Override
    public Result updateJob(Job job) {
        boolean flag = updateById(job);
        if (!flag)
            return Result.error("修改失败");
        return Result.ok(null, "修改成功");
    }

    @Override
    public Result updateType(Long id, Integer type) {
        boolean update = lambdaUpdate()
                .set(Job::getType, type)
                .eq(Job::getId, id)
                .update();
        if (!update)
            return Result.error("修改失败");
        return Result.ok(null, "修改成功");
    }

    /**
     * 获取用户岗位
     *
     * @param page
     * @param size
     * @param type
     * @return
     */
    @Override
    public Result getUserJob(Integer page, Integer size, Integer type) {
        Long userId = UserContext.getUser().getId();
        //ObjectMapper objectMapper = new ObjectMapper();
        //JSONUtil.toJsonStr()

        if (page == null) page = 1;
        if (size == null) size = 10;
        Page<Job> page1 = lambdaQuery()
                .eq(Job::getType, type)
                .eq(Job::getUserId, userId)
                .orderByDesc(Job::getUpdateTime)
                .page(Page.of(page, size));
        List<Job> jobList = page1.getRecords();
        int total = (int) page1.getTotal();
        int pages = (int) page1.getPages();

        //LambdaQueryChainWrapper<Job> lambdaQuery = lambdaQuery();
        //LambdaQueryWrapper<Job> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        //List<Job> list = list(lambdaQuery);
        //baseMapper.selectList(lambdaQueryWrapper);
        //List<Job> list = lambdaQuery().eq(Job::getUserId, userId).list();
        return Result.ok(PageResult.of(total, pages, jobList));
    }

    @Override
    public Result getSearcherList(Integer page, Integer size, String input) {
        List<Job> jobs = list().stream().filter(job ->
                job.getType() == 1
        ).collect(Collectors.toList());

        if (page == null) page = 1;
        if (size == null) size = 8;
        Page<Job> page1 = lambdaQuery()
                .eq(Job::getType, 1)
                .like(Job::getTitle, input)
                .page(Page.of(page, size));

        List<Job> jobList = page1.getRecords();
        int total = (int) page1.getTotal();
        int pages = (int) page1.getPages();

        return Result.ok(PageResult.of(total, pages, jobList));
    }

    @Override
    public Map<Long, Job> getByIds(Set<Long> companyIds) {
        List<Job> jobList = lambdaQuery()
                .in(Job::getId, companyIds)
                .list();
        Map<Long, Job> jobMap = jobList.stream()
                .collect(Collectors.toMap(Job::getId, job -> job));
        return jobMap;
    }

    /**
     * 根据id 查询具体的岗位详情
     *
     * @param id
     * @return
     */
    @Override
    public Result getJobDetails(Long id) {
        Job job = lambdaQuery()
                .eq(Job::getId, id)
                .eq(Job::getType, 1)
                .one();
        //Job job = getById(id);
        if (job == null) {
            return Result.error("该岗位已消失");
        }
        User user = userService.getById(job.getUserId());
        Company company = companyService.getById(job.getCompanyId());
        JobCollection collection = collectionService.lambdaQuery()
                .eq(JobCollection::getUserId, UserContext.getUser().getId())
                .eq(JobCollection::getJobId, id)
                .one();
        JobVO vo = new JobVO();
        BeanUtil.copyProperties(job, vo);
        vo.setUserName(user.getName());
        vo.setImage(user.getImage());
        vo.setCompany(company.getName());
        vo.setAddress(company.getAddress());
        vo.setCompanyImage(company.getImage());
        vo.setIntroduction(company.getIntroduction());
        if (collection != null) vo.setIsCollection(1);
        else vo.setIsCollection(0);
        return Result.ok(vo);
    }


    public boolean isTrueOfParameter(Job job) {
        if (job == null)
            return false;
        if (StrUtil.isBlank(job.getTitle()) || StrUtil.isBlank(job.getContent()) ||
                StrUtil.isBlank(job.getSalary()) || StrUtil.isBlank(job.getEducational()) ||
                StrUtil.isBlank(job.getJobType())) {
            return false;
        }
        return true;
    }


    @Override
    public Result queryJobList(Integer page, Integer size) {
        Page<Job> jobPage = lambdaQuery()
                .page(Page.of(page, size));
        List<Job> jobList = jobPage.getRecords();
        int total = (int) jobPage.getTotal();
        int pages = (int) jobPage.getPages();
        if (CollectionUtil.isEmpty(jobList)) {
            Result.ok(PageResult.of(total, pages, null));
        }
        return Result.ok(PageResult.of(total, pages, jobList));
    }

    @Override
    public Result updateJobAdmin(Job job) {
        updateById(job);
        return Result.ok("修改成功");
    }
}
